package com.crawler.gmail.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jsoup.internal.StringUtil;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Set;

/**
 * Created by wangbo on 15/12/31.
 */
public class JsonUtil {
    public static final String DATEFORMAT_ISO8601 = "yyyy-MM-dd HH:mm:ss";
    public static final String DATEFORMAT_UTC = "yyyy-MM-dd'T'HH:mm:ss'+08:00'";
    static final ObjectMapper mapper = new ObjectMapper();

    static {
        mapper.setDateFormat(new SimpleDateFormat(DATEFORMAT_UTC));
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
    }

    public static void setDateFormat(String dateFormat) {
        mapper.setDateFormat(new SimpleDateFormat(dateFormat));
    }

    public static String toJson(Object obj) {
        if (obj == null) {
            return null;
        }
        if (obj.getClass() == String.class) {
            return obj.toString();
        }
        String json;
        try {
            json = mapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        return json;
    }


    public static <T> T fromJson(String content, Class<T> classType) {
        if (!jsonCheck(content)) {
            return null;
        }
        if (classType == String.class) {
            return (T) content;
        }
        try {
            return mapper.readValue(content, classType);
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    public static <T> T fromJson(String content, TypeReference<T> valueTypeRef) {
        if (!jsonCheck(content)) {
            return null;
        }
        try {
            return (T) mapper.readValue(content, valueTypeRef);
        } catch (IOException e) {
            throw new RuntimeException(String.format("json:%s\nmsg:%s", content, e.getMessage()), e);
        }
    }

    static boolean jsonCheck(String content) {
        if (content == null || "".equals(content)) {
            return false;
        }
//        if (!(content.startsWith("{") && content.endsWith("}"))) {
//            throw new RuntimeException(String.format("json数据格式错误，无法完成反序列化:\n%s", content));
//        }
        return true;
    }

    public static boolean compareJSONArrayIsEquals(String str1, String str2) {

        boolean flag = true;

        JSONArray newJsonArray = JSONArray.parseArray(StringUtil.isBlank(str1) ? "[]" : str1);
        JSONArray oldJsonArray = JSONArray.parseArray(StringUtil.isBlank(str2) ? "[]" : str2);
        if (newJsonArray.size() != oldJsonArray.size()) {
            flag = false;
            return flag;
        }
        for (int i = 0; i < newJsonArray.size(); i++) {
            Object newObject = newJsonArray.get(i);
            HashMap<String, Object> newHashMap = JSONObject.parseObject(newObject.toString(), HashMap.class);
            boolean findFlag = true;
            for (int j = 0; j < oldJsonArray.size(); j++) {
                Object oldObject = oldJsonArray.get(j);
                HashMap<String, Object> oldHashMap = JSONObject.parseObject(oldObject.toString(), HashMap.class);
                findFlag = true;
                if (newHashMap.size() == oldHashMap.size()) {
                    Set<String> keySet = newHashMap.keySet();
                    for (String key : keySet) {
                        String nValue = newHashMap.get(key).toString();
                        String oValue = oldHashMap.get(key).toString();
                        if (StringUtil.isNumeric(nValue) && StringUtil.isNumeric(oValue)) {
                            if (new BigDecimal(nValue).compareTo(new BigDecimal(oValue)) != 0) {
                                findFlag = false;
                                break;
                            }
                        } else {
                            if (!nValue.equals(oValue)) {
                                findFlag = false;
                                break;
                            }
                        }
                    }
                }
                if (findFlag == true) {
                    break;
                }
            }
            if (!findFlag) {
                flag = false;
                return flag;
            }
        }
        return flag;
    }
}
